package com.xidian.bankdemo.service.impl;

import com.xidian.bankdemo.dto.ListDTO;
import com.xidian.bankdemo.dto.QueryDTO;
import com.xidian.bankdemo.dto.StatementDTO;
import com.xidian.bankdemo.dto.TransactionDTO;
import com.xidian.bankdemo.entity.Account;
import com.xidian.bankdemo.entity.Friend;
import com.xidian.bankdemo.entity.Log;
import com.xidian.bankdemo.entity.Transaction;
import com.xidian.bankdemo.mapper.AccountMapper;
import com.xidian.bankdemo.mapper.FriendMapper;
import com.xidian.bankdemo.mapper.TransactionMapper;
import com.xidian.bankdemo.service.AccountService;
import com.xidian.bankdemo.service.LogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.List;

@Slf4j
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private FriendMapper friendMapper;
    @Autowired
    private TransactionMapper transactionMapper;
    @Autowired
    private LogService logService;

    @Override
    public List<Account> getList(Long ownerId) {
        return accountMapper.findByOwnerId(ownerId);
    }

    @Override
    public List<Account> getAll() {
        return accountMapper.findAll();
    }

    @Override
    public List<Friend> getFriendList(Long ownerId) {
        return friendMapper.findByOwnerId(ownerId);
    }

    @Override
    public int addAccount(Account account) {
        if (account.getId() == null) return -1;
        if (accountMapper.existsById(account.getId())) return 0;
        int result = accountMapper.insertAccount(account);
        logService.addLog(new Log(LogService.CREATE, "账户:"+account.getId(), result, "管理员添加账户"));
        return result;
    }

    @Override
    public int editAccount(Account account) {
        int result = accountMapper.updateAccount(account);
        logService.addLog(new Log(LogService.UPDATE, "账户:"+account.getId(), result, "管理员修改账户"));
        return result;
    }

    @Override
    public int delAccount(Long id) { // fixme： 同时删除与账号相关的交易记录
        int result = accountMapper.deleteAccount(id);
        logService.addLog(new Log(LogService.DELETE, "账户:"+id, result, "管理员删除账户"));
        return result;
    }

    @Deprecated
    @Transactional
    @Override
    public int doWithdrawal(TransactionDTO transactionDTO) {
        int r = accountMapper.updateBalanceById(transactionDTO.getMyAccount(), transactionDTO.getAmount().negate());
        log.info(transactionDTO.toString());
        Transaction transaction = new Transaction(transactionDTO.getMyAccount(),
                0L,
                transactionDTO.getName(),
                "外部账户",
                transactionDTO.getAmount(),
                "用户取款",
                r==1?0:1);
        return transactionMapper.insertTransaction(transaction);
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public int doTransaction(TransactionDTO transactionDTO) {
        log.debug(transactionDTO.toString());

        Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
        int r1 = accountMapper.updateBalanceById(transactionDTO.getMyAccount(), transactionDTO.getAmount().negate());
        int r2 = accountMapper.updateBalanceById(transactionDTO.getToAccount(), transactionDTO.getAmount());
        int result = r1+r2;
        log.info("{}=>取出{}",transactionDTO.getMyAccount(),r1==1?"成功":"失败");
        log.info("{}<=存入{}",transactionDTO.getToAccount(),r2==1?"成功":"失败");
        if (result == 2){
            result = 1;// 成功
            if (!friendMapper.existsByAccount(transactionDTO.getToAccount(), transactionDTO.getId())) {
                Friend friend = new Friend(transactionDTO.getToAccount(),
                        transactionDTO.getToUsername(),
                        transactionDTO.getToBankName(),
                        transactionDTO.getId());
                friendMapper.insertFriend(friend);
            }
        } else {
            // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//全部回滚
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint);//回滚到保存点
            log.warn("用户转账: 事务回滚");
            result = 0;// 失败
        }

        Transaction transaction = new Transaction(transactionDTO.getMyAccount(),
                transactionDTO.getToAccount(),
                transactionDTO.getName(),
                transactionDTO.getToUsername(),
                transactionDTO.getAmount(),
                transactionDTO.getDescription(),
                result);

        logService.addLog(new Log(LogService.CREATE, "转账记录", result, "用户转账"));
        return transactionMapper.insertTransaction(transaction);
    }

    @Override
    public ListDTO getStatementList(QueryDTO query) {
        log.debug(query.toString());
        ListDTO list = new ListDTO();
        if (query.getMyAccount()==null) {
            list.setTotal(-1);
            return list;
        }
        List<StatementDTO> statementList = transactionMapper.findIncomeByQuery(query);
        statementList.addAll(transactionMapper.findOutcomeByQuery(query));

        list.setStatementList(statementList);// fixme: sql的时间比较
        list.setTotal(list.getStatementList().size());

        return list;
    }

    @Override
    public ListDTO getTransactionList(QueryDTO query) {
        log.debug(query.toString());
        ListDTO list = new ListDTO();

        List<Transaction> transactionList = transactionMapper.findByQuery(query);
        list.setTransactionList(transactionList);// fixme: sql的时间比较
        list.setTotal(transactionList.size());

        return list;
    }
}
